<?php
/**
 * ThinkPHP TCP 服务器 - 修复版本
 */

define('APP_PATH', __DIR__ . '/application/');
require __DIR__ . '/vendor/autoload.php';


use Workerman\Worker;
use Workerman\Connection\TcpConnection;



// 协议编码函数
function encodeMessage($data)
{
    if (is_array($data)) {
        $data = json_encode($data, JSON_UNESCAPED_UNICODE);
    }
    
    $length = str_pad(strlen($data), 8, '0', STR_PAD_LEFT);
    return $length . $data;
}

// // 协议解码函数
// function decodeMessage($data)
// {
//     if (strlen($data) < 8) {
//         return false;
//     }
    
//     $length = intval(substr($data, 0, 8));
//     $jsonData = substr($data, 8, $length);
    
//     if (strlen($jsonData) !== $length) {
//         return false;
//     }
    
//     return json_decode($jsonData, true);
// }

// 记录连接日志函数
function logConnection($action, TcpConnection $connection)
{
    $logData = [
        'action' => $action,
        'client_ip' => $connection->getRemoteIp(),
        'client_port' => $connection->getRemotePort(),
        'connection_id' => $connection->id,
        'timestamp' => date('Y-m-d H:i:s')
    ];
    
    echo "📝 连接日志: " . json_encode($logData, JSON_UNESCAPED_UNICODE) . "\n";
}

// 创建TCP Worker监听2346端口
$tcpWorker = new Worker('tcp://0.0.0.0:2346');
$tcpWorker->count = 4;

// 存储所有连接的客户端
$tcpWorker->connections = new \SplObjectStorage;

/**
 * 当客户端连接时触发 - 修复版本
 */
$tcpWorker->onConnect = function(TcpConnection $connection) use ($tcpWorker) {
    $clientIp = $connection->getRemoteIp();
    $clientPort = $connection->getRemotePort();
    $connectionId = $connection->id;
    
    echo "✅ 新的TCP客户端连接: {$clientIp}:{$clientPort} [ID: {$connectionId}]\n";
    
    // 将连接保存到连接池
    $tcpWorker->connections->attach($connection);
    
    // 设置连接属性
    $connection->connect_time = time();
    $connection->client_id = uniqid('client_');
    $connection->last_activity = time();
    
    // 发送欢迎消息 - 使用函数而不是 $this
    $jd = [
        'client_id' => $connection->client_id,
        'server_time' => date('Y-m-d H:i:s'),
        'version' => '1.0.0'
    ];
    $welcomeMessage = [
        'action' => 'system',
        'code' => 200,
        'message' => '连接ThinkPHP服务器成功',
        'data' => json_encode($jd)
    ];
    
    $encodedMessage = encodeMessage($welcomeMessage); // 使用函数调用
    $connection->send($encodedMessage);
    
    // 记录连接日志
    logConnection('connect', $connection);
};

/**
 * 当收到客户端数据时触发
 */
$tcpWorker->onMessage = function(TcpConnection $connection, $data) use ($tcpWorker) {
    // 更新最后活动时间
    $connection->last_activity = time();
    
    echo "📨 收到来自 {$connection->getRemoteIp()} 的数据，长度: " . strlen($data) . " 字节\n";
    // echo $data . "\n";
    try {
        // 1. 解析协议
        $index=0;
        for($i;$i<strlen($data);$i++){
            $check = substr($data,$i,1);
            // echo $check." ";
            if($check=="{"){
                $index = $i;
                echo "第n个={".$index."\n";
                break;
            }
        }

        // echo "第n222个={".$index."\n";
        $data = substr($data,$index);
        echo "去除后的data = ". $data . "\n";
       

        $request = json_decode($data,true); // 使用函数调用
        if (!$request) {
            throw new Exception('数据格式错误');
        }
        
        // 2. 记录原始请求
        // echo "📝 解析后的请求: " . json_encode($request, JSON_UNESCAPED_UNICODE) . "\n";
        
        // 3. 处理业务逻辑
        $response = handleRequest($connection, $request); // 使用函数调用
        
        if( $response==""){

        }else 
        // 4. 发送响应
        if ($response) {
            $encodedResponse = encodeMessage($response); // 使用函数调用
            $connection->send($encodedResponse);
            echo "📤 发送响应到客户端" . json_encode($response). "\n";
        }
        
    } catch (Exception $e) {
        $errorResponse = [
            'type' => 'error',
            'code' => 500,
            'message' => $e->getMessage(),
            'timestamp' => time()
        ];
        
        $encodedError = encodeMessage($errorResponse); // 使用函数调用
        $connection->send($encodedError);
        // echo "❌ 处理错误: " . $e->getMessage() . "\n";
    }
};

/**
 * 处理业务请求的函数
 */
function handleRequest(TcpConnection $connection, $request)
{
    $action = $request['action'] ?? 'unknown';
    
    echo "🎯 处理请求: action={$action}\n";
    
    try {
        switch ($action) {
            case 'login':
                return handleLogin($connection, $request);
                
            case 'heartbeat':
                return handleHeartbeat($connection, $request);
                
            case 'get_data':
                return handleGetData($connection, $request);
            case 'chat':
                    return handleChat($connection, $request);
            case 'getchat':
                // return "";
                    return handleGetChat($connection, $request);
            default:
                return [
                    'type' => 'error',
                    'code' => 404,
                    'message' => "未知操作: {$action}",
                    'timestamp' => time()
                ];
        }
    } catch (Exception $e) {
        return [
            'type' => 'error',
            'code' => 500,
            'message' => '业务处理错误: ' . $e->getMessage(),
            'timestamp' => time()
        ];
    }
}

/**
 * 处理登录请求的函数
 */
function handleLogin(TcpConnection $connection, $request)
{
    $username = $request['username'] ?? '';
    $password = $request['password'] ?? '';
    
    echo "🔐 处理登录请求: username={$username}\n";
    
    if (empty($username) || empty($password)) {
        throw new Exception('用户名和密码不能为空');
    }
    
    // 模拟用户验证
    if ($username === 'admin' && $password === '123456') {
        $connection->user_id = 1;
        $connection->username = $username;
        $connection->is_authenticated = true;
        
        return [
            'action' => 'login_response',
            'code' => 200,
            'message' => '登录成功',
            'data' => json_encode([
                'user_id' => 1,
                'username' => $username,
                'token' => md5($username . time()),
                'login_time' => date('Y-m-d H:i:s')
            ])
        ];
    } else {
        throw new Exception('用户名或密码错误');
    }
}

/**
 * 处理心跳请求的函数
 */
function handleHeartbeat(TcpConnection $connection, $request)
{
    $connection->last_heartbeat = time();
    
    // echo "💓 心跳检测 - 客户端: {$connection->getRemoteIp()}\n";
    
    return [
        'action' => 'heartbeat_response',
        'code' => 200,
        'message' => 'pong',
        'data' => json_encode([
            'server_time' => date('Y-m-d H:i:s'),
            'client_id' => $connection->client_id ?? 'unknown'
        ])
    ];
}



$G=[];
/**
 * 处理获取数据请求的函数
 */
function handleChat(TcpConnection $connection, $request)
{
    global $G;
    echo "================聊天处理";
    // // 检查认证
    
    $dd = json_decode($request['data'],true);
    echo json_encode($dd, JSON_UNESCAPED_UNICODE) . "\n";
    $date = date("Y-m-d");
    $c=[];

    if(empty($G["chat"])){
        $G["chat"]=[];
        
        $G["chat"][$date]=[];
    }else{
        // 假设 $G["chat"] 的 key 是日期格式，如 '2024-01-15'
        foreach ($G["chat"] as $dateKey => $value) {
            // 将数组key和比较日期转换为时间戳
            $keyTimestamp = strtotime($dateKey);
            $compareTimestamp = strtotime($date);
    
            // 判断key是否比$date2早2天或以上
            if ($compareTimestamp - $keyTimestamp >= 2 * 24 * 60 * 60) {
                 // 删除这个key
                unset($G["chat"][$dateKey]);
                echo "删除过期key: {$dateKey}\n";
            }else{
                $c[$dateKey] = count($G["chat"][$dateKey]);
            }
        }
        if(empty($G["chat"][$date])){
            $G["chat"][$date]=[];
        }
    }
    $dd["index"]=count($G["chat"][$date]);

    $G["chat"][$date][] = $dd;

    echo "聊天记录\n";
    echo json_encode($G["chat"], JSON_UNESCAPED_UNICODE);

    return [
        'action' => 'chat_response',
        'code' => 200,
        'data' => json_encode($c),
        'timestamp' => time()
    ];
}

function handleGetChat(TcpConnection $connection, $request)
{
    global $G;
    // // 检查认证
    $date = json_decode($request['data'],true);
    $day = date("Y-m-d");

    $res=[];
    $res["data"]=[];
    $res["count"]=[];

    echo json_encode($G, JSON_UNESCAPED_UNICODE);
    echo "\n";
    echo json_encode($date, JSON_UNESCAPED_UNICODE);

    if(empty($G["chat"])){
        $G["chat"]=[];
        
        $G["chat"][$date]=[];
    }else{
        // 假设 $G["chat"] 的 key 是日期格式，如 '2024-01-15'
        foreach ($G["chat"] as $dateKey => $value) {
            // 将数组key和比较日期转换为时间戳
            $keyTimestamp = strtotime($dateKey);
            $compareTimestamp = strtotime($day);

            echo $dateKey."\n";
            echo isset($date[$dateKey])."\n";
            echo json_encode($date, JSON_UNESCAPED_UNICODE);
    
            // 判断key是否比$date2早2天或以上
            if ($compareTimestamp - $keyTimestamp >= 2 * 24 * 60 * 60) {
                 // 删除这个key
                unset($G["chat"][$dateKey]);
                echo "删除过期key: {$dateKey}\n";
            }else if(isset($date[$dateKey])){
                $index1 = $date[$dateKey];
                $index2 = count($G["chat"][$dateKey])-1;
                $len = $index2-$index1+1;

                echo $index1."  ".$index2."  ".$len."\n";
                if($index1-$index2>0){
                    echo "-0000000000000000-\n";
                }else if($index1-$index2==0){
                    echo "----------------------\n";
                    $list = [];
                    $list[] = $G["chat"][$dateKey][$index2];
                    $res["data"][$dateKey] = $list;
                    $res["count"][$dateKey] = $index2+1;
                }else{
                    echo "=====================\n";
                    $res["data"][$dateKey] = array_slice($G["chat"][$dateKey],$index1,$len);
                    $res["count"][$dateKey] = $index2+1;
                }
            }
        }
        if(!isset($G["chat"][$date])){
            $G["chat"][$date]=[];
        }
    }
   
    echo json_encode($res, JSON_UNESCAPED_UNICODE);

    return [
        'action' => 'getchat_response',
        'code' => 200,
        'data' => json_encode($res),
        'timestamp' => time()
    ];
}

/**
 * 处理获取数据请求的函数
 */
function handleGetData(TcpConnection $connection, $request)
{
    // 检查认证
    if (empty($connection->is_authenticated)) {
        throw new Exception('请先登录');
    }
    
    $dataType = $request['data_type'] ?? 'user_info';
    
    echo "📊 获取数据: type={$dataType}, user_id={$connection->user_id}\n";
    
    // 模拟数据查询
    $data = [
        'user_info' => [
            'user_id' => $connection->user_id,
            'username' => $connection->username,
            'level' => 10,
            'exp' => 1000
        ],
        'game_data' => [
            'score' => 5000,
            'coins' => 10000,
            'items' => ['sword', 'potion', 'shield']
        ]
    ];
    
    return [
        'action' => 'data_response',
        'code' => 200,
        'data' => $data[$dataType] ?? [],
        'timestamp' => time()
    ];
}

/**
 * 当客户端断开连接时触发
 */
$tcpWorker->onClose = function(TcpConnection $connection) use ($tcpWorker) {
    echo "🔌 客户端断开连接: {$connection->getRemoteIp()} [ID: {$connection->id}]\n";
    
    // 从连接池移除
    $tcpWorker->connections->detach($connection);
    
    // 记录断开日志
    logConnection('disconnect', $connection);
};

/**
 * 错误处理
 */
$tcpWorker->onError = function(TcpConnection $connection, $code, $msg) {
    echo "💥 TCP错误 [{$code}]: {$msg} - 客户端: {$connection->getRemoteIp()}\n";
};

// 心跳检测定时器
$tcpWorker->onWorkerStart = function($worker) {
    // echo "🔄 Worker进程启动: PID=" . posix_getpid() . "\n";
    echo "🔄 Worker进程启动: PID="  . "\n";
    
    // 每30秒检查一次心跳
    \Workerman\Timer::add(30, function() use ($worker) {
        $timeout = 300; // 5分钟超时
        $currentTime = time();
        $timeoutCount = 0;
        
        foreach ($worker->connections as $connection) {
            if (isset($connection->last_activity) && 
                ($currentTime - $connection->last_activity) > $timeout) {
                echo "⏰ 客户端超时断开: {$connection->getRemoteIp()}\n";
                $connection->close();
                $timeoutCount++;
            }
        }
        
        if ($timeoutCount > 0) {
            echo "⏰ 本次清理了 {$timeoutCount} 个超时连接\n";
        }
    });
};

// 启动服务器
echo "🎉 ThinkPHP TCP服务器启动成功\n";
echo "📍 监听地址: tcp://0.0.0.0:2346\n";
echo "👥 进程数量: {$tcpWorker->count}\n";
echo "⏰ 启动时间: " . date('Y-m-d H:i:s') . "\n";
echo "=" . str_repeat("=", 50) . "=\n";

Worker::runAll();